package com.ruoyi.exam.domain;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.ObjectUtil;
import lombok.Data;

import java.util.*;
import java.util.stream.Collectors;

@Data
public class ExamUnreal {
    private Integer id;
    private Long uid;
    private Integer quTotal;// 题库题目总数
    private Integer rights;  // 正确的数量
    private Integer dones;   // 已完成的题数
    private Integer rightRate; // 正确率
    private Integer doneRate; // 进度

    private String doneQuestionIds;
    private Set<Integer> doneQuestionIdSet;

    private String rightQuestionIds;
    private Set<Integer> rightQuestionIdSet;

    private String answerData;
    private Map<Integer ,String> answerDataMap;

    private Long questionBankVersion;

    private Date createTime;
    private Date updateTime;

    public void setDoneQuestionIds(String doneQuestionIds) {
        this.doneQuestionIds = doneQuestionIds;
        if(this.doneQuestionIds == null || StrUtil.isBlank(this.doneQuestionIds)){
            this.doneQuestionIds = "[]";
        }
        this.doneQuestionIdSet = new HashSet<>(JSON.parseArray(doneQuestionIds ,Integer.class));
    }

    public Set<Integer> getDoneQuestionIdSet() {
        if(doneQuestionIdSet == null){
            setDoneQuestionIds(getDoneQuestionIds());
        }
        return doneQuestionIdSet;
    }

    public void setRightQuestionIds(String rightQuestionIds) {
        this.rightQuestionIds = rightQuestionIds;
        if(this.rightQuestionIds == null || StrUtil.isBlank(this.rightQuestionIds)){
            this.rightQuestionIds = "[]";
        }
        this.rightQuestionIdSet = new HashSet<>(JSON.parseArray(rightQuestionIds ,Integer.class));
    }

    public Set<Integer> getRightQuestionIdSet() {
        if(rightQuestionIdSet == null){
            setRightQuestionIds(getRightQuestionIds());
        }
        return rightQuestionIdSet;
    }

    public void setAnswerData(String answerData) {
        this.answerData = answerData;
        JSONObject obj = JSON.parseObject(answerData);
        if(obj != null){
            this.answerDataMap = obj.entrySet().stream()
                    .collect(Collectors.toMap(entry -> Integer.parseInt(entry.getKey()), entry -> entry.getValue().toString()));
        }else {
            this.answerDataMap = new HashMap<>();
        }
    }

    public Map<Integer, String> getAnswerDataMap() {
        if(answerDataMap == null){
            setAnswerData(getAnswerData());
        }
        return answerDataMap;
    }

    public static ExamUnreal buildDefault(long uid ,int quTotal){
        ExamUnreal examUnreal = new ExamUnreal();
        examUnreal.uid = uid;
        examUnreal.quTotal = quTotal;
        examUnreal.setDefault();
        examUnreal.setRights(0);
        examUnreal.setDones(0);
        examUnreal.setRightRate(0);
        examUnreal.setDoneRate(0);
        return examUnreal;
    }

    public void setDefault(){
        if(getAnswerData() == null || StrUtil.isBlank(getAnswerData())){
            setAnswerData("{}");
        }
        if(getDoneQuestionIds() == null || StrUtil.isBlank(getDoneQuestionIds())){
            setDoneQuestionIds("[]");
        }
        if(getRightQuestionIds() == null || StrUtil.isBlank(getRightQuestionIds())){
            setRightQuestionIds("[]");
        }
        questionBankVersion = System.currentTimeMillis();
        createTime = new Date();
        updateTime = createTime;
    }

    public void verifyComplete(){
        ObjectUtil.checkNull(uid ,"uid");
        ObjectUtil.checkNull(rights  ,"rights");
        ObjectUtil.checkNull(dones  ,"dones");
    }


    /**
     * 新增已答题
     * @param qid
     * @param answer
     * @param isRight
     */
    public void addAnswer(int qid ,String answer ,boolean isRight){
        this.dones++;
        if(this.quTotal > 0){
            this.doneRate = (int)((double)this.dones / this.quTotal * 100);
        }
        if(isRight){
            this.rights ++;
            Set<Integer> ris = this.getRightQuestionIdSet();
            if(ris == null){
                ris = new HashSet<>();
            }
            ris.add(qid);
            setRightQuestionIds(JSON.toJSONString(ris));
            this.rightRate = (int)((double)this.rights / this.dones * 100);
        }
        Set<Integer> set = getDoneQuestionIdSet();
        if(set == null){
            set = new HashSet<>();
        }
        set.add(qid);
        setDoneQuestionIds(JSON.toJSONString(set));

        Map<Integer ,String> map = getAnswerDataMap();
        if(map == null){
            map = new HashMap<>();
        }
        map.put(qid ,answer);
        setAnswerData(JSON.toJSONString(map));
    }

    /**
     * 题目是否已做
     * @param questionId
     * @return
     */
    public boolean idDone(int questionId){
        Set<Integer> set = getDoneQuestionIdSet();
        return set != null && set.contains(questionId);
    }

    public String getAnswer(int questionId){
        Map<Integer ,String> map = getAnswerDataMap();
        if(map != null){
            return map.get(questionId);
        }
        return null;
    }

    /**
     * 题库更新后操作
     * @param existDoneQids 更新后，题库还存在的已做题目ID
     */
    public void afterQuestionBankUpdate(int quTotal, List<Integer> existDoneQids){
        Set<Integer> dones = new HashSet<>(existDoneQids);
        Set<Integer> rightSet = getRightQuestionIdSet();

        this.dones =  existDoneQids.size();
        this.rights = (int) rightSet.stream().filter(r -> dones.contains(r)).count();

        this.quTotal = quTotal;

        this.questionBankVersion = System.currentTimeMillis();
    }
}
